package io.bdmc.common.utils;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;

public class CommonUtil {

    public static String getOrderIdByUUId() {
        int machineId = 1;// 最大支持1-9个集群机器部署
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if (hashCodeV < 0) {// 有可能是负数
            hashCodeV = -hashCodeV;
        }
        return machineId + String.format("%015d", hashCodeV);
    }

    /**
     * 数组集合转化为指定对象集合 指定的实体对象必须包含所以字段的构造方法，数组的元素的顺序将和构造方法顺序和类型一一对应
     * 
     * @param list
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    @SuppressWarnings("all")
    public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz) throws Exception {
        List<T> returnList = new ArrayList<>();
        if (list.size() == 0) {
            return returnList;
        }
        Class[] c2 = null;
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            Class[] tClass = constructor.getParameterTypes();
            if (tClass.length == list.get(0).length) {
                c2 = tClass;
                break;
            }
        }
        // 构造方法实例化对象
        for (Object[] o : list) {
            Constructor<T> constructor = clazz.getConstructor(c2);
            returnList.add(constructor.newInstance(o));
        }

        return returnList;
    }


    public static Object setField(Object dss, Map<String, Object> map) {
        Field[] fields = dss.getClass().getDeclaredFields();
        // 获得访问私有实例域的权限
        AccessibleObject.setAccessible(fields, true);
        for (Field field : fields) {
            try {
                if (map.get(field.getName()) == null) {
                    continue;
                }
                if (field.getGenericType().toString().equals("class java.lang.Integer")) {
                    int val = Integer.parseInt(map.get(field.getName()).toString());
                    field.set(dss, val);
                } else if (field.getGenericType().toString().equals("class java.math.BigDecimal")) {
                    BigDecimal d = new BigDecimal(map.get(field.getName()).toString());
                    field.set(dss, d);
                } else if (field.getGenericType().toString().equals("class java.lang.String")) {
                    String val = map.get(field.getName()).toString();
                    field.set(dss, val);
                }
                // field.set(dss, );
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return dss;
    }

    /*
     * 获取本机网内地址
     */
    public static List<String> getInet4Address() {
        try {
            List<String> ipAddLt = new ArrayList<>();
            // 获取所有网络接口
            Enumeration<NetworkInterface> allNetworkInterfaces = NetworkInterface.getNetworkInterfaces();
            // 遍历所有网络接口
            while (allNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = allNetworkInterfaces.nextElement();
                // 如果此网络接口为 回环接口 或者 虚拟接口(子接口) 或者 未启用 或者 描述中包含VM
                if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()
                        || networkInterface.getDisplayName().contains("VM")) {
                    // 继续下次循环
                    continue;
                }
                // 遍历此接口下的所有IP（因为包括子网掩码各种信息）
                for (Enumeration<InetAddress> inetAddressEnumeration = networkInterface
                        .getInetAddresses(); inetAddressEnumeration.hasMoreElements();) {
                    InetAddress inetAddress = inetAddressEnumeration.nextElement();
                    // 如果此IP不为空
                    if (inetAddress != null) {
                        // 如果此IP为IPV4 则返回
                        if (inetAddress instanceof Inet4Address) {
                            ipAddLt.add(inetAddress.getHostAddress());
                        }

                    }
                }
            }
            return ipAddLt;

        } catch (SocketException e) {
            e.printStackTrace();
            return null;
        }
    }
}